package game;

import sys.Logger;

import org.lwjgl.LWJGLException;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.ContextAttribs;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.PixelFormat;
import org.lwjgl.util.glu.GLU;

import sys.Profiling;
import sys.SysClock;
import sys.SysParam;

public abstract class M5CraftBase {
	public SysClock.Timer updaterTimer = SysClock.updaterTimer;

	public void startUp() throws LWJGLException {
		setupOpenGL();
	}

	public void shutDown() {
	}

	public void run() {
		SysClock.reset();
		Profiling profile = new Profiling();
		while (!Display.isCloseRequested() && !shouldStop()) {
			updaterTimer.resetLoopCounter();
			profile.frameBegin();
			profile.incremfFameCounter();
			while (updaterTimer.isOKForNextLoop()) {
				update();
				updaterTimer.tick();
			}
			render();
			// Display.sync(60);
			// Let the CPU synchronize with the GPU if GPU is tagging behind
			Display.update();
			profile.frameEnd();
			profile.print();
		}
	}

	protected void update() {
	}

	protected void render() {
		GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
		// float interpolation = updaterTimer.getInterpolation();
	}

	private void setupOpenGL() throws LWJGLException {
		Display.setTitle(SysParam.GAME_NAME);

		DisplayMode displayMode = new DisplayMode(SysParam.SCREEN_WIDTH, SysParam.SCREEN_WIDTH);
		Display.setDisplayMode(displayMode);
		Display.setVSyncEnabled(true);

		PixelFormat pixelFormat = new PixelFormat();
		ContextAttribs contextAttribs = new ContextAttribs(SysParam.GL_MAJOR_VER, SysParam.GL_MINOR_VER);
		contextAttribs.withForwardCompatible(SysParam.GL_FORWARD_COMPATIBLE);
		Display.create(pixelFormat, contextAttribs);

		Display.setResizable(false);
		GL11.glClearColor(0.4f, 0.6f, 0.9f, 0f);

		GL11.glEnable(GL11.GL_CULL_FACE);
		GL11.glCullFace(GL11.GL_BACK);
		GL11.glFrontFace(GL11.GL_CW);

		GL11.glEnable(GL11.GL_DEPTH_TEST);
		GL11.glDepthMask(true);
		GL11.glDepthFunc(GL11.GL_LEQUAL);
		GL11.glDepthRange(0, 1);

		Mouse.setGrabbed(true);
		exitOnGLError("Setup OpenGL");
	}

	public void resized() {
		GL11.glViewport(0, 0, SysParam.SCREEN_WIDTH, SysParam.SCREEN_WIDTH);
	}

	public boolean shouldStop() {
		return Keyboard.isKeyDown(Keyboard.KEY_ESCAPE);
	}

	protected void destroy() {
		if (Display.isCreated()) {
			Display.destroy();
		}
		System.exit(0);
	}

	protected void exitOnGLError(String errorMessage) {
		int errorValue = GL11.glGetError();
		if (errorValue == GL11.GL_NO_ERROR) {
			return;
		}

		String errorString = GLU.gluErrorString(errorValue);
		Logger.error("ERROR - " + errorMessage + ": " + errorString);
		destroy();
	}
}
